package com.example.back.Controller;

import com.example.back.Annotation.UserLoginToken;
import com.example.back.Entity.*;
import com.example.back.NonRepEntity.BuyerComment;
import com.example.back.NonRepEntity.ProductIdList;
import com.example.back.NonRepEntity.SoldNumAndLevel;
import com.example.back.NonRepEntity.StarsList;
import com.example.back.Repository.OrderItemRepository;
import com.example.back.Repository.ProductRepository;
import com.example.back.Repository.StarRepository;
import com.example.back.Repository.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("product")
public class ProductController {
    final int RETURN_PAGE_SIZE = 10;
    final int LARGE_RETURN_PAGE_SIZE = 24;

    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private StarRepository starRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private OrderItemRepository orderItemRepository;

    //上传商品
    @UserLoginToken
    @PostMapping("")
    public String addProduct(@RequestBody Product product) {
        product.setSaleDate(new Date());
        Product resultProduct = productRepository.save(product);
        //为方便前端上传图片时获取到productId，返回productId
        return resultProduct.getProductId() + "";
    }

    //根据ID查询商品
    @UserLoginToken
    @GetMapping("{proId}")
    public Product findProductByProductId(@PathVariable("proId") long proId) {
        return productRepository.findProductByProductId(proId);
    }

    //获取点赞数最高的前5个
    @UserLoginToken
    @GetMapping("/topF")
    public Page<Product> findTopFourProductByStarsNum(){
        Pageable pageable = PageRequest.of(0,5, Sort.Direction.DESC,"starsNum");
        return productRepository.findAll(pageable);
    }

    //根据商品名称和tag查询列表
    @UserLoginToken
    @GetMapping("/PNCTAG/{productNameContains}/{TagContains}/{OrderName}/{asc}/{page}")
    public Page<Product> findAllByPNCTAG(@PathVariable("productNameContains") String PNC,
                                         @PathVariable("TagContains") String TAG,
                                         @PathVariable("OrderName") String orderName,
                                         @PathVariable("asc") int asc,
                                         @PathVariable("page") int page) {
        Sort.Direction direction;
        if (asc == 1)
            direction = Sort.Direction.ASC;
        else
            direction = Sort.Direction.DESC;
        Pageable pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, direction, orderName);
        return productRepository.findAllByTagContainsAndProductNameContains(pageable, TAG, PNC);
    }

    //根据tag来查询列表
    @UserLoginToken
    @GetMapping("/tag/{tagName}/{orderName}/{asc}/{page}")
    public Page<Product> findAllByTagContains(@PathVariable("tagName") String tagName,
                                              @PathVariable("orderName") String orderName,
                                              @PathVariable("asc") int asc,
                                              @PathVariable("page") int page) {
        Sort.Direction direction = asc == 1 ? Sort.Direction.ASC : Sort.Direction.DESC;
        Pageable pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, direction, orderName);
        return productRepository.findAllByTagContains(pageable, tagName);
    }

    //点赞
    @UserLoginToken
    @PatchMapping("/stars/{act}/{pid}/{uId}/{pName}/{coverUUID}")
    public boolean patchProductStars(@PathVariable("pid") long pid,
                                     @PathVariable("act") boolean act,//是否点赞
                                     @PathVariable("uId") long uId,
                                     @PathVariable("pName") String pName,
                                     @PathVariable("coverUUID") String coverUUID) {
        try {
            Product Tproduct = findProductByProductId(pid);
            if (act) {
                if (isProductStars(uId, pid)) {//如果已经点赞了
                    return false;
                }
                Tproduct.setStarsNum(Tproduct.getStarsNum() + 1);
                //保存点赞
                Star Tstar = new Star();
                Tstar.setStarProductId(pid);
                Tstar.setStarUserId(uId);
                Tstar.setStarProductName(pName);
                Tstar.setCoverUUID(coverUUID);
                Tstar.setStarDate(new Date());
                starRepository.save(Tstar);
            } else {
                //取消点赞
                Tproduct.setStarsNum(Tproduct.getStarsNum() - 1);
                //在star数据库中删除点赞
                starRepository.deleteById(starRepository.findStarByStarUserIdAndStarProductId(uId, pid).getStarId());
            }
            productRepository.save(Tproduct);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    //判断用户是否给当前商品点赞
    @UserLoginToken
    @GetMapping("/stars/isS/{uId}/{pId}")
    public boolean isProductStarsOuter(@PathVariable("uId") long uId,
                                       @PathVariable("pId") long pId) {
        return isProductStars(uId, pId);
    }

    //获取点赞列表
    @UserLoginToken
    @PostMapping("/stars/isSList")
    public List<Boolean> isProductStarsList(@RequestBody StarsList starsList) {
        int size = starsList.getProductIdList().size();
        List<Boolean> resultList = new ArrayList<>(LARGE_RETURN_PAGE_SIZE);
        for (int i = 0; i < size; i++) {
            resultList.add(isProductStars(starsList.getUserId(), starsList.getProductIdList().get(i)));
        }
        return resultList;
    }

    private boolean isProductStars(long uId, long pId) {
        return starRepository.findStarByStarUserIdAndStarProductId(uId, pId) != null;

    }

    //获取当前用户所有点赞
    @UserLoginToken
    @GetMapping("/starList/{uId}/{page}")
    public Page<Star> findAllStarsByUserId(@PathVariable("uId") long uId,
                                           @PathVariable("page") int page) {
        //点赞界面的组件较小，要每页返回多一点
        Pageable pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, Sort.Direction.ASC, "starDate");
        return starRepository.findStarsByStarUserId(uId, pageable);
    }

    //给商品增加评价
    @UserLoginToken
    @PatchMapping("/comments/{act}/{pid}")
    public boolean patchProductComments(@PathVariable("pid") long pid,
                                        @PathVariable("act") boolean act) {
        try {
            Product Tproduct = findProductByProductId(pid);
            if (act) {
                Tproduct.setCommentsNum(Tproduct.getCommentsNum() + 1);
            } else
                Tproduct.setCommentsNum(Tproduct.getCommentsNum() - 1);
            productRepository.save(Tproduct);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    //根据商品名进行查询
    @Cacheable("productName")
    @UserLoginToken
    @GetMapping("/PNC/{PNContains}/{orderName}/{asc}/{page}")
    public Page<Product> findAllByProductNameContains(@PathVariable("PNContains") String PNC,
                                                      @PathVariable("orderName") String orderName,
                                                      @PathVariable("asc") int asc,
                                                      @PathVariable("page") int page) {
        Pageable pageable;
        if (asc == 1)
            pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, Sort.Direction.ASC, orderName);
        else
            pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, Sort.Direction.DESC, orderName);
        return productRepository.findAllByProductSoldAndProductNameContains(pageable, false, PNC);
    }

    //根据卖家查询商品列表
    @UserLoginToken
    @GetMapping("/belongTo/{blTId}/{page}")
    public Page<Product> findAllByBelongToId(@PathVariable("blTId") long blTId,
                                             @PathVariable("page") int page) {
        Pageable pageable = PageRequest.of(page - 1, RETURN_PAGE_SIZE);
        return productRepository.findAllByBelongToId(pageable, blTId);
    }

    //    @Cacheable("product")
    //根据排序方式查询全部商品
    @UserLoginToken
    @GetMapping("/list/{orderName}/{asc}/{page}")
    public Page<Product> findAllOrderBy(@PathVariable("orderName") String orderName,
                                        @PathVariable("asc") int asc,
                                        @PathVariable("page") int page) {
        Pageable pageable;
        if (asc == 1) {
            pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, Sort.Direction.ASC, orderName);
        } else {
            pageable = PageRequest.of(page - 1, LARGE_RETURN_PAGE_SIZE, Sort.Direction.DESC, orderName);
        }
        return productRepository.findAllByProductSold(pageable, false);
    }

    //设置为卖出
    @UserLoginToken
    @PatchMapping("/sale/{pid}")
    public void setProductSale(@PathVariable("pid") long pId) {
        productRepository.setProductSoldByProductId(pId);
    }

    /*
      将被购买的商品库存减一
      如果是最后一件则将商品置为已卖出
     */
    @UserLoginToken
    @PatchMapping("/buy/{productId}")
    public boolean minusStock(@PathVariable("productId") long productId) {
        Product tempProduct = productRepository.findProductByProductId(productId);
        if (tempProduct.getProductStock() > 1) {
            tempProduct.setProductStock(tempProduct.getProductStock() - 1);
            return true;
        } else if (tempProduct.getProductStock() == 1) {
            //将商品设置为已卖出
            tempProduct.setProductStock(0);
            productRepository.setProductSoldByProductId(productId);
            return true;
        }
        return false;
    }

    //更新库存
    @UserLoginToken
    @PatchMapping("/stock/{productId}/{newStock}")
    public boolean updateStockByProductId(@PathVariable("productId") long productId,
                                          @PathVariable("newStock") int newStock) {
        if (newStock < 0)
            return false;
        productRepository.updateProductStockByProductId(productId, newStock);
        return true;
    }

    //将列表置为已卖出
    @UserLoginToken
    @PatchMapping("/saleList")
    public void setProductListSoldById(@RequestBody ProductIdList IdList) {
        List<Long> productIdList = IdList.getProductIdList();
        for (Long productId : productIdList) {
            productRepository.setProductSoldByProductId(productId);
        }
    }

    //给商品评价
    @UserLoginToken
    @PatchMapping("/comment")
    public boolean buyerComment(@RequestBody BuyerComment buyerComment) {
        //获取卖家原来的评价
        SoldNumAndLevel SNAL = userRepository.getNumAndLevelByUserId(buyerComment.getBuyerId());

        //更新卖家的信息
        int soldNum = SNAL.getSoldNum();
        double oldSLevel = SNAL.getServiceLevel();//服务质量
        double newSLevel = getAvg(soldNum, oldSLevel, buyerComment.getServiceLevel());
        double oldLLevel = SNAL.getLogisticsLevel();//物流服务
        double newLLevel = getAvg(soldNum, oldLLevel, buyerComment.getLogisticsLevel());
        double oldPLevel = SNAL.getProductLevel();//商品质量
        double newPLevel = getAvg(soldNum, oldPLevel, buyerComment.getProductLevel());

        userRepository.updateSellerInfo(soldNum + 1, newSLevel, newLLevel, newPLevel, buyerComment.getBuyerId());
        //设置商品的评价
        productRepository.setProductLevelByProductId(buyerComment.getProductLevel(), buyerComment.getProductId());
        //更新订单的状态
        orderItemRepository.setNewState("已评价", buyerComment.getOrderId());
        return true;
    }

    private double getAvg(int num, double oldNum, double newNum) {
        return (oldNum * num + newNum) / (num + 1);
    }

    //删除商品
    @UserLoginToken
    @DeleteMapping("{productId}")
    public boolean deleteProductByProductId(@PathVariable("productId") long productId) {
        try {
            productRepository.deleteById(productId);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    //删除多个商品
    @UserLoginToken
    @DeleteMapping("/list")
    public void deleteAllProductByProductIdIn(@RequestBody long[] productIds) {
        productRepository.deleteAllByProductIdIn(productIds);
    }
}
